#include "slist.h"
#include "stdio.h"
#include "stdlib.h"

#define list_for_each(pos, head) \
	for (pos = head->next; pos != NULL; pos = pos->next)

int init_slist(Node *list)
{
	list->next = NULL;
	return 0;
}

int destroy_slist(Node *list)
{
	Pnode pos = NULL;
	list_for_each(pos, list) {
		if (pos->data != NULL) {
			free(pos->data);
		}
		free(pos);
	}
	return 0;
}

bool is_slist_empty(Node *list)
{
	if (list->next == NULL) {
		return true;
	} else {
		return false;
	}
}

int len_of_slist(Node *list)
{
	int num = 0;
	Pnode pos;
	list_for_each(pos, list) {
		num++;
	}
	return num;
}

int get_elem(Node *list, int loc, void **value)
{
	Pnode pos;
	int __loc = 0;
	list_for_each(pos, list) {
		__loc++;
		if (__loc == loc) {
			*value = pos->data;
			return 0;
		}
	}
	printf("E: slist: no such value\n");
	return -1;
}

int locate_elem(Node *list, int *loc, CMP_VALUE_T cmp_func, void *data)
{
	Pnode pos = NULL;
	int __loc = 0;
	list_for_each(pos, list) {
		__loc++;
		if (true == cmp_func(list, data)) {
			*loc = __loc;
			return 0;
		}
	}
	return -1;
}

int prior_elem(Node *list, CMP_VALUE_T cmp_func, void *data, void *prior_data)
{
	int loc = 0;
	if (locate_elem(list, &loc, cmp_func, data)) {
		printf("E: slist: locate elem error\n");
		return -1;
	}
	if (get_elem(list, loc, prior_data)) {
		printf("E: slist: get prior data error\n");
		return -1;
	}
	return 0;
}

int next_elem(Node *list, CMP_VALUE_T cmp_func, void *data, void *next_data)
{
	int loc = 0;
	if (locate_elem(list, &loc, cmp_func, data)) {
		printf("E: slist: locate elem error\n");
		return -1;
	}
	next_data = (void *)((Pnode)data)->next;
	return 0;
}

int insert_elem(Node *list, int loc, Node *node)
{
	Pnode pos = list;
	int flag = 0;
	if (loc <= 0) {
		return -1;
	}
	for (loc--; loc; loc--) {
		pos = pos->next;
		if (pos == NULL) {
			break;
			flag = 1;
		}
	}
	if (flag == 1) {
		return -1;
	}
	node->next = pos->next;
	pos->next = node;
	return 0;
}

int delete_elem(Node *list, int loc)
{
	Pnode pos = list;
	Pnode tmp;
	if (loc <= 0 || loc > len_of_slist(list)) {
		return -1;
	}
	for (loc--; loc; loc--) {
		pos = pos->next;
	}
	tmp = pos->next;
	pos->next = tmp->next;
	free(tmp->data);
	free(tmp);
}
